/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.uc.service.impl;

import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.domain.bo.TeamBO;
import com.xy.biz.uc.domain.bo.TeamUserRelBO;
import com.xy.biz.uc.domain.bo.UserBO;
import com.xy.biz.uc.domain.bo.UserGroupBO;
import com.xy.biz.uc.domain.query.TeamQuery;
import com.xy.biz.uc.domain.query.TeamUserRelQuery;
import com.xy.biz.uc.domain.query.UserGroupIdQuery;
import com.xy.biz.uc.domain.query.UserGroupQuery;
import com.xy.biz.uc.domain.req.ListUserGroupByGroupName;
import com.xy.biz.uc.domain.req.ListUserGroupItemRequest;
import com.xy.biz.uc.domain.resp.GetUserGroupResponse;
import com.xy.biz.uc.domain.resp.ListUserGroupItemResponse;
import com.xy.biz.uc.domain.vo.GroupRoleUserTree;
import com.xy.biz.uc.domain.vo.GroupUserTreeItem;
import com.xy.biz.uc.manager.TeamManager;
import com.xy.biz.uc.manager.UserGroupManager;
import com.xy.biz.uc.service.UserGroupService;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.treeing.Tree;
import com.xy.lang.domain.treeing.TreeItem;
import com.xy.lang.util.UuidUtils;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.xy.biz.uc.domain.bo.UserGroupBO.JOIN_STATUS_JOINED;

/**
 *
 *
 * @author zsp
 * @date 2020-8-20
 */
@Service
public class UserGroupServiceImpl implements UserGroupService {

    @Autowired
    private UserGroupManager userGroupManager;
    @Autowired
    private TeamManager teamManager;
    @Autowired
    private UserClient userClient;

    @Override
    public Result<?> saveUserGroup(UserGroupBO userGroupBO) {
        //默认设置部门简称，不允许重复
        userGroupBO.setUserGroupAbbr(UuidUtils.compactSystemUuid().substring(0, 16));
        Long tenantId = UserContextHolder.getTenantId();
        userGroupBO.setTenantId(tenantId);
        if (userGroupBO.getParentUserGroupId() == null) {
            userGroupBO.setParentUserGroupId(0L);
        }
        LocalDateTime now = LocalDateTime.now();
        userGroupBO.setCreateUserId(UserContextHolder.getUserId());
        userGroupBO.setCreateTime(now);
        userGroupBO.setUpdateTime(now);
        userGroupBO.addUserBO(UserBO.builder()
                .userId(UserContextHolder.getUserId())
                .joinStatus(JOIN_STATUS_JOINED)
                .joinTime(now)
                .build());
        int affectedRows = userGroupManager.saveUserGroup(userGroupBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateUserGroup(UserGroupBO userGroupBO) {
        if (userGroupBO.getParentUserGroupId() == null) {
            userGroupBO.setParentUserGroupId(0L);
        } else {
            Long userGroupId = userGroupBO.getUserGroupId();
            if (Objects.equals(userGroupId, userGroupBO.getParentUserGroupId())) {
                return Result.ofErrorData("设置了错误的上级部门");
            } else {
                Long parentUserGroupId = userGroupBO.getParentUserGroupId();
                List<Long> childrenUserGroupIdList = userGroupManager.listChildrenUserGroupId(userGroupId);
                if (!CollectionUtils.isEmpty(childrenUserGroupIdList)
                        && childrenUserGroupIdList.stream().anyMatch(e -> Objects.equals(parentUserGroupId, e))) {
                    return Result.ofErrorData("设置了错误的上级部门");
                }
            }
        }
        userGroupBO.setUpdateTime(LocalDateTime.now());
        int affectedRows = userGroupManager.updateUserGroup(userGroupBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteUserGroup(Long userGroupId) {
        int affectedRows = userGroupManager.deleteUserGroup(userGroupId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public UserGroupBO getUserGroup(UserGroupIdQuery query) {
        return userGroupManager.getUserGroup(query);
    }

    @Override
    public List<UserGroupBO> listUserGroupById(UserGroupIdQuery query) {
        return userGroupManager.listUserGroupById(query);
    }

    @Override
    public List<UserGroupBO> listUserGroup(UserGroupQuery query) {
        return userGroupManager.listUserGroup(query);
    }

    /**
     * 查找多个
     *
     * @param request 查找条件
     */
    @Override
    public List<UserGroupBO> listUserGroupByGroupName(ListUserGroupByGroupName request) {
        if (request.getGroupName() == null || ("").equals(request.getGroupName())) {
            return null;
        }
        return userGroupManager.listUserGroupByGroupName(request.getGroupName());
    }

    @Override
    public int countUserGroup(UserGroupQuery query) {
        return userGroupManager.countUserGroup(query);
    }

    @Override
    public List<ListUserGroupItemResponse> listUserGroupItem(ListUserGroupItemRequest request) {
        return userGroupManager.listUserGroupItem(request);
    }

    @Override
    public List<Long> listRoleIdByUserGroupId(Long userGroupId) {
        return userGroupManager.listRoleIdByUserGroupId(userGroupId);
    }

    @Override
    public List<GetUserGroupResponse> listUserGroupBy(UserGroupQuery query) {
        return userGroupManager.listUserGroupBy(query);
    }

    /**
     * @author Greekn Zhang
     * @date 2021/5/8 16:50
     * @return com.xy.biz.uc.domain.vo.GroupRoleUserTree
     * @description 除人员外的公司架构树
     */
    @Override
    public GroupRoleUserTree listGroups() {
        List<ListUserGroupItemResponse> responses = userGroupManager.listUserGroupItem(ListUserGroupItemRequest.builder().build());
        List<TreeItem> treeItems = new ArrayList<>();
        if (!CollectionUtils.isEmpty(responses)) {
            treeItems = Tree.buildTreeItem(responses,
                    e -> e.getSource().getUserGroupId(),
                    e -> e.getSource().getParentUserGroupId(),
                    e -> e == null || e == 0,
                    e -> e.getUserGroupId().toString(),
                    ListUserGroupItemResponse::getUserGroupName,
                    null,
                    null);
        }
        List<GroupUserTreeItem> gTree = new ArrayList<>();
        getGroupItem(treeItems, gTree);
        List<GroupUserTreeItem> teamUserTreeItems = buildTeamTree();
        return new GroupRoleUserTree(gTree, null, teamUserTreeItems);
    }


    /**
     * @author Greekn Zhang
     * @date 2021/5/7 10:51
     * @param treeItems
     * @description 构建公司部门树
     */
    private void getGroupItem(List<TreeItem> treeItems, List<GroupUserTreeItem> g) {
        if (treeItems.isEmpty()) {
            return;
        }
        for (TreeItem tree : treeItems) {
            GroupUserTreeItem gt = new GroupUserTreeItem();
            gt.setId(Long.parseLong(tree.getValue()));
            gt.setLabel(tree.getLabel());
            if (tree.getChildren() != null) {
                gt.setChildren(new ArrayList<>());
                gt.setPerson(false);
                getGroupItem(tree.getChildren(), gt.getChildren());
            }
            g.add(gt);
        }
    }

    /**
     * @author Greekn Zhang
     * @date 2021/5/27 16:21
     * @return java.util.List<com.xy.biz.uc.domain.vo.GroupUserTreeItem>
     * @description 构建团队人员树
     */
    private List<GroupUserTreeItem> buildTeamTree() {
        GroupUserTreeItem teamUserTreeItem = new GroupUserTreeItem();
        List<TeamBO> teamBOS = teamManager.listTeam(TeamQuery.max().build());
        if (CollectionUtils.isEmpty(teamBOS)) {
            return null;
        }
        Map<Long, List<TeamUserRelBO>> map = new HashMap<>();
        if (teamBOS != null) {
            //添加团队
            ArrayList<GroupUserTreeItem> userItems = new ArrayList<>();
            teamBOS.forEach(teamBO -> {
                GroupUserTreeItem userItem = new GroupUserTreeItem();
                userItem.setId(teamBO.getTeamId());
                userItem.setLabel(teamBO.getTeamName());
                userItem.setPerson(false);
                userItems.add(userItem);
                teamUserTreeItem.setChildren(userItems);
                List<TeamUserRelBO> teamUserRelBOS = teamManager.listTeamUserRel(TeamUserRelQuery.builder().teamId(teamBO.getTeamId()).joinStatus(TeamUserRelBO.JOIN_STATUS_JOINED).build());
                map.put(teamBO.getTeamId(), teamUserRelBOS);
            });
        }
        //向团队中添加人
        List<GroupUserTreeItem> children = teamUserTreeItem.getChildren();
        children.forEach(team -> {
            if (map.containsKey(team.getId())) {
                List<TeamUserRelBO> teamUserRelBOS = map.get(team.getId());
                ArrayList<GroupUserTreeItem> userItems = new ArrayList<>();
                teamUserRelBOS.forEach(rel -> {
                    GroupUserTreeItem userItem = new GroupUserTreeItem();
                    userItem.setId(rel.getUserId());
                    userItem.setPerson(true);
                    userItems.add(userItem);
                    team.setChildren(userItems);
                });
                if (!CollectionUtils.isEmpty(team.getChildren())) {
                    userClient.buildByUser(team.getChildren(),
                            team.getChildren().stream().map(GroupUserTreeItem::getId).collect(Collectors.toList()),
                            GroupUserTreeItem::getId,
                            (group, userDTO) -> group.setLabel(userDTO.getUserName()));
                }
            }
        });
        return children;
    }
}
